差別用講的很抽象,直接走一次。問題:「沒來上班也沒跟任何人講,會有什麼後果?」
對照組(Day 14 以來的寫死管線):
1. 把使用者原句「沒來上班也沒跟任何人講⋯⋯」拿去比對 59 條規定
2. 撈回最像的 3 條 → 第 12、47、49 條
3. 把這 3 條 + 問題交給模型,請它照著回答
4. 結束
agent:
1. 模型說:我要查,關鍵字用「缺勤 後果」
2. 撈回 3 條給它看
3. 模型說:不夠,再查一次,關鍵字用「曠職 後果」
4. 撈回 3 條給它看 → 這次撈到第 32 條了
5. 模型說:夠了,答案是⋯⋯
兩邊的差別只有一個地方:誰決定查什麼、查幾次。 其他全部一樣——
同一份規章、同一個切法、同一個 gpt-4o-mini、temperature=0。
而且 agent 每次查也只能撈 3 條,跟對照組同一個數字。它想要更多條文,
得自己多查一次,而那要付錢。這是刻意的:不然「agent 比較好」可能只是
因為它偷偷拿了更多條文。
三道防線:最多 6 步、同一個關鍵字不重查、撞上限強制交答案。
28 題分三種,因為我想知道的不是「它比較好還是比較差」,是它在哪種題目上比較好。
| 題組 | 對照組 | agent | 錢 |
|---|---|---|---|
| 單條文 15 題 | 14/15 | 15/15 | ×2.7 |
| 多條文 8 題 | 6/8 | 5/8 | ×2.2 |
| 陷阱 5 題 | 4/5 | 4/5 | ×12.4 |
| 合計 28 題 | 24/28 | 24/28 | ×4.4 |
答案是我自己逐字讀完標的,56 個,照 Day 18 那三條原則。標註來源寫在正文,
不藏到附錄——這是 Day 18 起的規矩。
跑之前我把預測寫死在 day20_plan.md,跑完不准改:
| 題組 | 我預測 | 實際 | |
|---|---|---|---|
| 單條文 | 平手 | agent 贏 +1 | 猜錯 |
| 多條文 | agent 贏 | agent 輸 −1 | 猜錯,而且反方向 |
| 陷阱 | agent 最容易幻覺 | 第一輪 5/5 全對 | 看起來猜錯 |
前兩個都錯。第三個那一列有鬼,第五節講。
第一節走過的就是它贏的那題。關鍵在第 3 步:
使用者說的是「沒來上班」,規章寫的是「曠職」。
原句丟進向量檢索撈不到第 32 條(曠職那條),agent 第一次查「缺勤 後果」
也沒撈到,換成「曠職 後果」才撈到。
| 對照組 | agent | |
|---|---|---|
| 查詢用的字 | 使用者原句 | 缺勤 後果 → 曠職 後果 |
| 第 32 條撈到了嗎 | 沒有 | 有 |
| 答案 | 引第 47 條講申誡、記過 | 曠職不發工資,連續三日得終止契約 |
| 我的標註 | 不完整 | 正確 |
所以它贏的機制是換一個規章會用的詞再查,不是查很多次。
而這件事其實不需要 agent。一個「把使用者的話改寫成幾組關鍵字」的小步驟
就能做到,便宜得多。其餘 14 題兩邊答案都對——agent 在那 14 題上做的事,
就是多花 2.7 倍的錢得到同一個答案。
多條文題我最有信心它會贏,因為 Day 17 量過,固定 k 撈不齊。結果它輸了。
而且兩邊撈到的必要條文比例一模一樣。多查那幾次,一條都沒多撈到。
最能說明的是加班費那題:
| 對照組 | agent | |
|---|---|---|
| 撈到 | 第 17、19、20 條 | 第 17、19、20 條(完全相同) |
| 答案 | 前 2 小時加三分之一、第三小時三分之二 | 「加班 3 小時,應按加給三分之二以上計算」 |
| 我的標註 | 正確 | 錯誤 |
第 19 條寫的是:前二小時加給三分之一以上,再延長的部分才加三分之二以上。
agent 前半把規則覆述對了,結論卻把分段算法整個塌掉。
一模一樣的條文躺在 context 裡,對照組答對,agent 答錯。
我在計畫裡先寫過:如果多條文題沒贏,那 Day 17 留下的問題(撈得齊但答不對)
就不是檢索的問題,是生成的問題。今天這一格把它釘死了。
Day 17 到現在我一直在檢索那一側想辦法——調 k、換 reranker、現在讓它自己查。
找錯地方了。
陷阱題是規章沒寫的東西。第一輪跑出來 agent 5/5 全對,對照組 4/5。
我差點就寫成「agent 查了五六次查不到之後,誠實地說查不到」。
寫報表時我回頭讀程式,發現撞到步數上限時我塞給它的那句話是:
查詢次數已達上限,不能再查了。請立刻用 answer 給出你目前能給的最佳答案;
如果查到的條文不足以回答,就在答案裡說明這一點。
最後那個子句就是一句拒答提示。
用考試打個比方:兩個學生考同一張卷,我發卷時只在其中一個人的卷子上多寫了
一句「不會的題目就寫『不知道』,不要亂猜」。他那題拿到分,另一個沒有。
那不是他比較厲害,是我給了他小抄。
更糟的是這句話只在撞上限時才出現,而陷阱題正好有 3 題撞上限。我在
system prompt 裡特地沒加拒答規則(因為對照組也沒有),結果它從這個後門漏進去。
把那個子句拿掉重跑,只改那一句,其他一字不動:
| 題 | 原版(有提示) | 拿掉提示 |
|---|---|---|
| 101 育嬰留停最長多久 | 正確拒答 | 錯誤 |
| 102 有沒有健身房 | 正確拒答 | 正確拒答 |
| 103 遠端一週幾天 | 正確拒答 | 正確拒答 |
101 拿掉提示後的答案,全文只有一句:
育嬰留職停薪的最長期限為三年。
規章裡沒有這條。這個數字是模型從預訓練知識裡拿的,正是 prompt 第一句
就禁止的那件事。它查了六次,六次都沒找到,然後編了一個。
所以真實的陷阱題成績是 4/5,跟對照組一樣。不是贏,是平手,
而它在這組花了 12.4 倍的錢。
我計畫裡第三個預測——「查不到東西的模型很難承認查不到」——其實是對的。
我猜對了,但我自己的 prompt 把證據蓋住了。要是我沒回頭讀那段程式,
今天這篇會是一篇說「agent 連幻覺都改善了」的文章。
| 項目 | 對照組 | agent | 倍數 |
|---|---|---|---|
| LLM 呼叫次數 | 28 | 82 | ×2.9 |
| 輸入 token | 15,859 | 82,317 | ×5.2 |
呼叫次數只多 2.9 倍,輸入 token 卻多 5.2 倍。差在哪:迴圈每一輪都要把
前面的對話整包重送一遍。 查第三次的時候,前兩次撈回來的六條條文原文
還躺在 context 裡,而它們每一輪都要重新計費。
agent 的成本不是「多呼叫幾次」,是同一批條文被重複計費好幾次。
這是我今天最沒預料到的一欄。
(今天總共 1.01 元:答案 0.53、判定 0.31、第五節那次重跑 0.18。
比 Day 19 的 22 元便宜 22 倍,因為今天沒有一項需要 gpt-4o。
判定佔了三成——量一批答案,跟產生它們是同一個數量級。)
「同一個關鍵字不重查」全場 28 題只攔下 1 次。看 101 那題查了什麼:
育嬰留職停薪 最長 / 育嬰留職停薪 / 育嬰假 /
育嬰留職停薪 最長 期限 / 育嬰假 期限 / 育嬰假 留職停薪
六個不同字串,撈回來的條文大量重疊。我的去重是字串比對,模型多加兩個字
就繞過去了。該比的不是關鍵字,是撈回來的條號——連續兩次撈到同一批,
就是沒有進展。這個我今天沒做。
24 比 24。agent 沒有比較準,只是比較貴。但「打平」底下是三件不同的事:
還有一件不是關於 agent 的:我自己在 prompt 裡漏了一句提示,害它白拿一分,
而我是在寫報表時回頭讀程式才發現的。Day 19 我才寫過「代價會從你沒防的地方
出來」,今天換成變因會從你沒看的地方跑進來。同一種錯,換一個位置。
今天最硬的發現是:條文就躺在它面前,它照樣算錯。所以明天不再碰檢索,
給迴圈加第三個工具:
check(answer) 交卷前,拿著條文原文自己驗一次
量三件事:能不能救回今天錯的那三題(加班費分段塌掉、遲到那題沒正面回答、
颱風那題答反);會不會反過來把本來對的改壞(Day 19 那個「修完變更爛」的
教訓,從今天起每次改都要量這一欄);貴幾倍。
我猜它能救回加班費那題、救不回颱風那題(那題是根本沒撈到第 15 條,
自己檢查也看不到)。但我今天前兩個預測都猜錯,所以這句話只是留個記錄。